package com.shao.utils.zookeeper;

import com.shao.constant.ZookeeperCons;
import com.shao.exception.DiscoveryException;
import com.shao.exception.ZookeeperException;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @author PaoFu
 * @version 1.0
 * @data 2025/4/8 15:43
 */
@Slf4j
public class ZookeeperUtils {

    /**
     * 创建zookeeper实例
     * @return 返回zookeeper实例
     */
    public static ZooKeeper createZookeeper() {
        return createZookeeper(ZookeeperCons.DEFAULT_CONNECT_ADDR, ZookeeperCons.DEFAULT_SESSION_TIMEOUT);
    }

    /**
     * 创建zookeeper实例
     * @param connectAddr 链接地址
     * @param timeout 超时时间
     * @return 返回zookeeper实例
     */
    public static ZooKeeper createZookeeper(String connectAddr, int timeout) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        final ZooKeeper zooKeeper;
        try {
            zooKeeper = new ZooKeeper(connectAddr, timeout,
                    event -> {
                        if (event.getState() == Watcher.Event.KeeperState.SyncConnected) {
                            // 连接成功就放行
                            log.info("连接成功");
                            countDownLatch.countDown();
                        }
                    }
            );
            countDownLatch.await();
            return zooKeeper;
        } catch (IOException | InterruptedException e) {
            log.error("初始化Zookeeper失败：" , e);
            throw new ZookeeperException();
        }
    }

    /**
     * 创建节点目录
     *
     * @param zooKeeper  zookeeper实例
     * @param watcher    watcher实例
     * @param node       节点
     * @param ids        权限
     * @param createMode 节点类型
     */
    public static void createZookeeperNode(ZooKeeper zooKeeper, Watcher watcher, ZookeeperNode node,
                                           ArrayList<ACL> ids, CreateMode createMode) {
        try {
            if (zooKeeper.exists(node.getNodePath(), watcher) != null) {
                log.error("节点【{}】已存在，创建失败", node.getNodePath());
                return;
            }
            zooKeeper.create(node.getNodePath(), node.getNodeData(), ids, createMode);
            log.info("节点【{}】创建成功", node.getNodePath());
        } catch (KeeperException | InterruptedException e) {
            log.error("创建节点【{}】发生异常", node.getNodePath());
            throw new ZookeeperException(e);
        }
    }

    /**
     * 关闭zookeeper实例
     * @param zooKeeper zookeeper实例
     */
    public static void closeZookeeper(ZooKeeper zooKeeper) {
        try {
            zooKeeper.close();
        } catch (InterruptedException e) {
            log.error("zookeeper断开连接失败：", e);
            throw new ZookeeperException();
        }
    }

    /**
     * 判断节点是否不存在
     * @param zooKeeper zookeeper实例
     * @param nodePath 节点路径
     * @param watcher watcher实例
     * @return boolean
     */
    public static boolean nodeIsNotExist(ZooKeeper zooKeeper, String nodePath, Watcher watcher) {
        try {
            return zooKeeper.exists(nodePath, watcher) == null;
        } catch (KeeperException | InterruptedException e) {
            log.error("判断节点【{}】是否不存在发生异常：", nodePath, e);
            throw new ZookeeperException(e);
        }
    }

    public static List<String> getChildren(ZooKeeper zooKeeper, String serviceNode, Watcher watcher) {
        if (nodeIsNotExist(zooKeeper, serviceNode, watcher)) {
            log.error("服务节点【{}】不存在", serviceNode);
            throw new ZookeeperException();
        }
        try {
            return zooKeeper.getChildren(serviceNode, watcher);
        } catch (KeeperException | InterruptedException e) {
            log.error("查找节点【{}】的子节点时发生异常", serviceNode, e);
            throw new ZookeeperException();
        }
    }
}
